/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：太平金科-基础组件封装层-SpringBoot组件封装-核心依赖
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taipingframework.boot.web.security;

import com.google.common.collect.ImmutableList;
import com.taipingframework.utility.exception.SystemInterrupterException;
import com.taipingframework.boot.web.response.status.ExceptionStatusEnum;
import com.taipingframework.utility.constant.SystemConstant;
import com.taipingframework.utility.exception.ApplicationException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.Keys;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Base64;

/**
 * 生成一对 公钥/私钥
 */
@Slf4j
@Getter
public class KeyPairBuilder {

    private KeyPairBuilder() {
    }

    /**
     * 使用支持非对称签名的算法 创建一对 公钥/私钥
     */
    public static KeyPairBuilder build() throws ApplicationException {
        return build(SignatureAlgorithm.RS256);
    }

    /**
     * 生成一对 公钥/私钥
     *
     * @param algorithm 支持非对称签名的算法
     */
    public static KeyPairBuilder build(SignatureAlgorithm algorithm) throws ApplicationException {
        try {
            if (!ImmutableList.of(SignatureAlgorithm.RS256, SignatureAlgorithm.RS384, SignatureAlgorithm.RS512,
                    SignatureAlgorithm.PS256, SignatureAlgorithm.PS384, SignatureAlgorithm.PS512,
                    SignatureAlgorithm.ES256, SignatureAlgorithm.ES384, SignatureAlgorithm.ES512)
                    .contains(algorithm)) {
                throw new SystemInterrupterException(ExceptionStatusEnum.UNSUPPORTED_ALGORITHM_ASYMMETRIC);
            }

            KeyPair keyPair = Keys.keyPairFor(algorithm);
            String privateKey = Encoders.BASE64.encode(keyPair.getPrivate().getEncoded());
            String publicKey = Encoders.BASE64.encode(keyPair.getPublic().getEncoded());

            KeyPairBuilder keyPairBuilder = new KeyPairBuilder();
            keyPairBuilder.setKeyPair(keyPair);
            keyPairBuilder.setPublicKey(publicKey);
            keyPairBuilder.setPrivateKey(privateKey);

            return keyPairBuilder;
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 生成一对 公钥/私钥
     */
    public static KeyPairBuilder build(String algorithm) throws ApplicationException {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(StringUtils.isBlank(algorithm) ? "RSA" : algorithm);
            keyPairGenerator.initialize(SystemConstant.BASE_UNIT);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            KeyPairBuilder keyPairBuilder = new KeyPairBuilder();
            keyPairBuilder.setKeyPair(keyPair);
            keyPairBuilder.setPublicKey(Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()));
            keyPairBuilder.setPrivateKey(Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()));

            return keyPairBuilder;
        } catch (Exception e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 公钥/私钥
     */
    private KeyPair keyPair;

    /**
     * 公钥
     */
    private String publicKey;

    /**
     * 私钥
     */
    private String privateKey;

    private void setKeyPair(KeyPair keyPair) {
        this.keyPair = keyPair;
    }

    private void setPublicKey(String publicKey) {
        this.publicKey = publicKey;
    }

    private void setPrivateKey(String privateKey) {
        this.privateKey = privateKey;
    }

}
